package edu.uwm.cs552;

import java.awt.BasicStroke;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Stroke;

import edu.uwm.cs552.util.Pair;

/**
 * The state of track laid down by a player in the game.
 * Track starts in state {@link #startBuildState()} and then
 * progresses turn by turn until it is {@link #BUILT}.
 * A player may plan construction through the use of {@link #PROPOSED}.
 */
public enum RailState {
	BUILT(null),
	BUILD1(new float[]{9.5f,1,9.5f}),
	BUILD2(new float[]{4.5f,1,9,1,4.5f}),
	BUILD3(new float[]{3,1,5.5f,1,5.5f,1,3}),
	BUILD4(new float[]{2,1,4,1,4,1,4,1,2}),
	BUILD5(new float[]{1.5f,1,3,1,3,1,3,1,3,1,1.5f}),
	BUILD6(new float[]{1.5f,1,2,1,2,1,3,1,2,1,2,1,1.5f}),
	BUILD7(new float[]{0,   1,2,1,2,1,2,1,2,1,2,1,2,1,1}),
	BUILD8(new float[]{1,   1,1,1,2,1,1,1,2,1,1,1,2,1,1,1,1}),
	BUILD9(new float[]{1,   1,1,1,1,1,1,1,1,1,2,1,1,1,1,1,1,1,1}),
	BUILD10(new float[]{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}),
	PROPOSED(new float[]{1,3,1,2,1,2,1,3,1,2,1,2}); 
	
	public void draw(Graphics2D g, HexEdge e, double scale) {
		Stroke savedStroke = g.getStroke();
		g.setStroke(getStroke(scale));
		Pair<HexCoordinate,HexCoordinate> hs = e.getHexagons();
		Point p1 = hs.fst.toPoint(scale);
		Point p2 = hs.snd.toPoint(scale);
		g.drawLine(p1.x, p1.y, p2.x, p2.y);
		g.setStroke(savedStroke);
	}
	
	private final float[] dashPatternModel;
	private static final float MODEL_SIZE = 20;
	
	private RailState(float[] model) {
		if (model != null) {
			float sum = 0;
			for (float f : model) {
				sum += f;
			}
			assert sum == MODEL_SIZE : "dash pattern not correct";
		}
		dashPatternModel = model;
	}
	
	/**
	 * Return the state of when building just starts.
	 * @return the stateof a rail just starting to be laid.
	 */
	public static RailState startBuildState() {
		return BUILD10;
	}
	
	/**
	 * Return the state of the track after a certain number of turns.
	 * Fully built track and proposed track are not affected.
	 * @param turns turns of the game that have passed.
	 * @return the state of the track after this many turns.
	 */
	public RailState progress(int turns) {
		if (this == PROPOSED) return this;
		if (this.ordinal() <= turns) return BUILT;
		return values()[this.ordinal()-turns];
	}
	
	private transient float lastScale = 0;
	private transient Stroke lastStroke = null;
	
	private Stroke getStroke(double scale) {
		if (scale == lastScale) return lastStroke;
		lastScale = (float)scale;
		float width = lastScale / 10;
		if (dashPatternModel == null) {
			lastStroke = new BasicStroke(width,BasicStroke.CAP_ROUND,BasicStroke.JOIN_ROUND);
		} else if (lastScale == MODEL_SIZE) {
			lastStroke = new BasicStroke(width,BasicStroke.CAP_BUTT,1,BasicStroke.JOIN_BEVEL,dashPatternModel,0);
		} else {
			float[] dashes = new float[dashPatternModel.length];
			for (int i=0; i < dashPatternModel.length; ++i) {
				dashes[i] = dashPatternModel[i] * lastScale / MODEL_SIZE;
			}
			lastStroke = new BasicStroke(width,BasicStroke.CAP_BUTT,BasicStroke.JOIN_BEVEL,1,dashes,0);
		}
		return lastStroke;
	}
}
